
#include "../UnitTestSystemCode/cpptest.h"
#include "../MathCode/Math.h"


class TSMatrix4x4 : public Test::Suite
{
private:
	float *testMatrixData;
	
public:
	TSMatrix4x4 ()
	{
		TEST_ADD(TSMatrix4x4::TestCtor);
		
		TEST_ADD(TSMatrix4x4::TestColumnAndRowMajorOperations_InitializationAndConversion);
		TEST_ADD(TSMatrix4x4::TestColumnAndRowMajorOperations_NotEqualness);
		
		TEST_ADD(TSMatrix4x4::TestCreation_Translation);
		TEST_ADD(TSMatrix4x4::TestCreation_Scaling);
		
		TEST_ADD(TSMatrix4x4::TestIsIdentity);
	}
		
protected:
    virtual void setup ();
    virtual void tear_down ();
	
private:
	// Tests constructors
	void TestCtor ();
	
	// Tests initilaization of matrix with different data type and conversion methods to different data types
	void TestColumnAndRowMajorOperations_InitializationAndConversion ();
	// Tests the differences between row- and column- major types of matrixes
	void TestColumnAndRowMajorOperations_NotEqualness ();
	
	void TestCreation_Translation ();
	void TestCreation_Scaling ();
	
	void TestIsIdentity ();
};


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Implementation

void TSMatrix4x4::setup ()
{
	testMatrixData = new float[16];
	for (int i=0; i<16; i++)
		testMatrixData[i] = i;
}

void TSMatrix4x4::tear_down ()
{
	delete [] testMatrixData;
	testMatrixData = NULL;
}

void TSMatrix4x4::TestCtor ()
{
	Matrix4x4 mat;
	ASSERT(mat.IsIdentity());
}

void TSMatrix4x4::TestColumnAndRowMajorOperations_InitializationAndConversion ()
{
	Matrix4x4 mat;
	
	// ColumnMajor
	mat.InitWithData(testMatrixData, MatrixArrayType_ColumnMajor);
	
	float colMajData[16];
	mat.ConvertToColumnMajorArray(colMajData);
	
	for (int i=0; i<16; i++)
	{
		ASSERT(testMatrixData[i] == colMajData[i]);
	}
	
	// RowMajor
	mat.InitWithData(testMatrixData, MatrixArrayType_RowMajor);
	
	float rowMajData[16];
	mat.ConvertToRowMajorArray(rowMajData);
	
	for (int i=0; i<16; i++)
	{
		ASSERT(testMatrixData[i] == rowMajData[i]);
	}
}

void TSMatrix4x4::TestColumnAndRowMajorOperations_NotEqualness ()
{
	Matrix4x4 mat;
	
	mat.InitWithData(testMatrixData, MatrixArrayType_ColumnMajor);
	
	float colMajData[16];
	float rowMajData[16];
	mat.ConvertToColumnMajorArray(colMajData);
	mat.ConvertToRowMajorArray(rowMajData);
	
	// all elements
	for (int i=0; i<16; i++)
	{
		if (i==0 || i==5 || i==10 || i==15)	// main diagonal value
		{
			ASSERT(colMajData[i] == rowMajData[i]);
		}
		else 
		{
			ASSERT(colMajData[i] != rowMajData[i]);
		}
	}
}

void TSMatrix4x4::TestCreation_Translation ()
{
	float x = 1, y = 2, z = 3;
	
	Matrix4x4 mat;
	mat.InitWithTranslation(x, y, z);
	
	// primary condition
	ASSERT(mat.n[3][0] == x);
	ASSERT(mat.n[3][1] == y);
	ASSERT(mat.n[3][2] == z);
	
	// secondary condition
	mat.n[3][0] = mat.n[3][1] = mat.n[3][2] = 0;
	ASSERT(mat.IsIdentity());	
}

void TSMatrix4x4::TestCreation_Scaling ()
{
	float x = 1, y = 2, z = 3;
	
	Matrix4x4 mat;
	mat.InitWithScaling(x, y, z);
	
	// primary condition
	ASSERT(mat.n[0][0] == x);
	ASSERT(mat.n[1][1] == y);
	ASSERT(mat.n[2][2] == z);
	
	// secondary condition
	mat.n[0][0] = mat.n[1][1] = mat.n[2][2] = 1;
	ASSERT(mat.IsIdentity());
}

void TSMatrix4x4::TestIsIdentity ()
{
	Matrix4x4 mat;
	ASSERT(mat.IsIdentity());
	
	mat.InitWithIdentity();
	ASSERT(mat.IsIdentity());

	mat.InitWithData(testMatrixData, MatrixArrayType_ColumnMajor);
	ASSERT(!mat.IsIdentity());
	
	float onesMatrixData[16] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
	mat.InitWithData(onesMatrixData, MatrixArrayType_ColumnMajor);
	ASSERT(!mat.IsIdentity());
	
	mat.ctor();
	ASSERT(!mat.IsIdentity());
}






